package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"path/filepath"
	"strings"
    "strconv"
	"text/template"
)

// TypeScript 接口和类型模板
const (
	tsItemTemplate = `export type {{.Name}} = {
{{range $key, $value := .Fields}}  {{$key}}: {{$value}};
{{end}}} `

	tsInterfaceTemplate = `export interface {{.Name}} {
{{range $key, $value := .Fields}}  {{$key}}: {{$value}};
{{end}}} `
)

// 输出的ts内容
var (
	OutTsStr = ""
    ItemCnt = 0
)

// 通过反射自动生成 TypeScript 接口定义
func generateTSInterface(jsonData map[string]interface{}, interfaceName string) (string, error) {
	fields := make(map[string]string)

	for key, value := range jsonData {
		fields[key] = getType(value)
	}

	typeInfo := map[string]interface{}{
		"Name":   interfaceName,
		"Fields": fields,
	}

	tmpl, err := template.New("tsInterface").Parse(tsInterfaceTemplate)
	if err != nil {
		return "", err
	}

	var buf bytes.Buffer
	if err := tmpl.Execute(&buf, typeInfo); err != nil {
		return "", err
	}

	return buf.String(), nil
}

// 获取字段值的类型并处理嵌套
func getType(value interface{}) string {
	switch v := value.(type) {
	case string:
		return "string"
	case float64:
		return "number"
	case bool:
		return "boolean"
	case nil:
		return "any" // 处理 null 情况
	case []interface{}:
		if len(v) == 0 {
			return "any[]" // 空数组
		}
		// 对于非空数组，获取第一个元素类型，并返回数组类型
		elementType := getType(v[0])
		return elementType + "[]"
	case map[string]interface{}:
		// 处理嵌套对象
		ItemCnt += 1
		nestedTypeName := "Item"+ strconv.Itoa(ItemCnt)// 动态生成的名称
		fields := make(map[string]string)
		for key, val := range v {
			fields[key] = getType(val)
		}
		// 生成嵌套类型
		nestedTypeContent := map[string]interface{}{
			"Name":   nestedTypeName,
			"Fields": fields,
		}
		var nestedBuf bytes.Buffer
		nestedTmpl, err := template.New("nestedType").Parse(tsItemTemplate)
		if err == nil {
			if err := nestedTmpl.Execute(&nestedBuf, nestedTypeContent); err == nil {
				// 这里可以动态将生成的嵌套类型附加到最终输出中
				OutTsStr += nestedBuf.String()
				OutTsStr += "\r\n"
				fmt.Println(nestedBuf.String())
				return nestedTypeName
			}
		}
		return "any"
	default:
		return "any"
	}
}

// 从文件名中提取接口名称
func getInterfaceName(outputFile string) string {
	baseName := filepath.Base(outputFile)
	ext := filepath.Ext(baseName)
	return strings.TrimSuffix(baseName, ext) // 去掉扩展名
}

func main() {
	// 定义命令行参数
	jsonFile := flag.String("j", "", "Input JSON file")
	outputFile := flag.String("o", "", "Output TypeScript file")
	flag.Parse()

	// 确保输入和输出文件参数被提供
	if *jsonFile == "" || *outputFile == "" {
		flag.Usage()
		return
	}

	// 读取 JSON 文件
	jsonData, err := ioutil.ReadFile(*jsonFile)
	if err != nil {
		fmt.Println("Error reading JSON file:", err)
		return
	}

	// 解析 JSON 数据
	var parsedData map[string]interface{}
	err = json.Unmarshal(jsonData, &parsedData)
	if err != nil {
		fmt.Println("Error parsing JSON:", err)
		return
	}

	// 根据文件名获取接口名称
	interfaceName := getInterfaceName(*outputFile)

	// 生成 TypeScript 接口
	tsInterface, err := generateTSInterface(parsedData, interfaceName)
	if err != nil {
		fmt.Println("Error generating TypeScript interface:", err)
		return
	}

	OutTsStr += tsInterface

	// 将生成的接口写入输出文件
	err = ioutil.WriteFile(*outputFile, []byte(OutTsStr), 0644)
	if err != nil {
		fmt.Println("Error writing TypeScript file:", err)
		return
	}

	fmt.Println("TypeScript interface generated successfully:", *outputFile)
}
